#ifndef CUSTOM_COMMON_INCLUDED
#define CUSTOM_COMMON_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

#define PI 3.1415926

const float3x3 ACESInputMat = float3x3(
    0.59719, 0.35458, 0.04823,
    0.07600, 0.90834, 0.01566,
    0.02840, 0.13383, 0.83777
);

// ODT_SAT => XYZ => D60_2_D65 => sRGB
const float3x3 ACESOutputMat = float3x3(
     1.60475, -0.53108, -0.07367,
    -0.10208, 1.10813, -0.00605,
    -0.00327, -0.07276, 1.07602
);

float3 RRTAndODTFit(float3 v)
{
    float3 a = v * (v + 0.0245786) - 0.000090537;
    float3 b = v * (0.983729 * v + 0.4329510) + 0.238081;
    return a / b;
}

float3 ACESFitted(float3 color)
{
    color = mul(ACESInputMat, color);

    // Apply RRT and ODT
    color = RRTAndODTFit(color);

    color = mul(ACESOutputMat, color);

    // Clamp to [0, 1]
    color = clamp(color, 0.0, 1.0);

    return color;
}

float3 linear_srgb(float3 x)
{
    return x;
    //return mix(1.055 * pow(x, float3(1. / 2.4)) - 0.055, 12.92 * x, step(x, float3(0.0031308)));
}

float sdBox(in float2 p, in float2 b)
{
    float2 d = abs(p) - b;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}

float sdCircle(in float2 p, float radius)
{
    return length(p) - radius;
}

float4 opU(float4 d1, float4 d2)
{
    return (d1.w < d2.w) ? d1 : d2;
}

float4 Global_Sdf(in float2 origin)
{
    float Time = _Time.y;
    
    float4 distance = float4(0, 0, 0, 0);
    // float2 m = float2(sin(Time), cos(Time)) * 0.3 + float2(1.0, 0.5);
    // distance = float4(float3(0.0, 15.0, 0.0), sdCircle(origin - m, .01));
    // distance = opU(distance, float4(0, 0, 0, sdCircle(origin - float2(0.5, 0.25), 0.1)));
    // distance = opU(distance, float4(0, 0, 0, sdCircle(origin - float2(1.5, 0.25), 0.1)));
    // distance = opU(distance, float4(0, 0, 0, sdCircle(origin - float2(0.5, 0.75), 0.1)));
    // distance = opU(distance, float4(0, 0, 0, sdCircle(origin - float2(1.5, 0.75), 0.1)));
    // distance = opU(distance, float4(0.03, 0.4, 3.0, sdBox(origin - float2(1.0, 0.5), float2(0.2, .005))));

    // float2 m = float2(1.6, 0.5); //float2(sin(Time) * 2, cos(Time) * 0.5) * 0.3 + float2(1.0, 0.5);
    // distance = float4(float3(0.0, 5.0, 0.0), sdCircle(origin - m, .05));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2(-0.3, -0.3), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2(-0.3,  0.0), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2(-0.3,  0.3), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.0, -0.3), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.0,  0.0), .05)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.0,  0.3), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.3, -0.3), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.3,  0.0), .025)));
    // distance = opU(distance, float4(0.0, 0.0, 0.0, sdCircle(origin - float2(1.0, 0.5) + float2( 0.3,  0.3), .025)));

    float2 m = float2(sin(Time) * 2, cos(Time)) * 0.3 + float2(1.0, 0.5);
    distance = float4(float3(0.0, 3.0, 0.0) * (sin(Time) + 1.0), sdCircle(origin - m, .05));
    distance = opU(distance, float4(1., 0., 0, sdBox(origin - float2(sin(Time / 3.141592654) + 1.0, 0.6), float2(0.15, 0.025))));
    distance = opU(distance, float4(0.03, 0.4, 3.0, sdBox(origin - float2(1.0, 0.5), float2(0.2, .005))));
    // distance = float4(float3(0.0, 3.0, 0.0), sdCircle(origin - float2(1.0, 0.5), 0.1));
    return distance;
}

struct Attributes
{
    uint VertexID : SV_VertexID;
};

struct Vert2Frag
{
    float4 PositionCS : SV_POSITION;
    float2 ScreenUV : TEXCOORD0;
};

// Generate Pos & UV By VertexID
Vert2Frag BlitVertex(Attributes Input)
{
    Vert2Frag Output;
    
    float4 Pos = GetFullScreenTriangleVertexPosition(Input.VertexID);
    float2 UV = GetFullScreenTriangleTexCoord(Input.VertexID);

    Output.PositionCS = Pos;
    Output.ScreenUV = UV;
    return Output;
}

#endif